package com.ssf.domain.strategy.service.armory;

import com.ssf.domain.strategy.model.entity.StrategyAwardEntity;
import com.ssf.domain.strategy.model.entity.StrategyRuleEntity;
import com.ssf.domain.strategy.repository.IStrategyRepository;
import com.ssf.types.common.Constants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class StrategyArmoryDispatch implements IStrategyArmory,IStrategyDispatch{
    @Resource
    private IStrategyRepository strategyRepository;
    public void assembleStrategy(Long strategyId) {
        //根据策略id，从策略规则表中查找策略的全部规则
        List<StrategyRuleEntity> strategyRuleEntities = strategyRepository.getStrategyRuleEntityByStrategyId(strategyId);
        log.info("strategyRuleEntities:{}",strategyRuleEntities);
        StrategyRuleEntity strategyRuleEntity = strategyRuleEntities.stream().filter(entity -> entity.getRuleModel().equals(Constants.RULE_WEIGHT)).findFirst().orElse(null);
        if (strategyRuleEntity == null) { //没有找到权重规则，直接从策略奖品表中查找策略对应的所有奖品
            assembleStrategy(strategyId + "", strategyRepository.getStrategyAwardEntityByStrategyId(strategyId));
            return;
        }
        //找到权重规则，根据不同权重，找到对应的奖品，装配对应的抽奖map
        HashMap<Integer, List<Integer>> ruleWeights = strategyRuleEntity.splitRuleWeights();
        for (Map.Entry<Integer, List<Integer>> entry : ruleWeights.entrySet()) {
            String key=strategyId+"_"+entry.getKey();
            List<StrategyAwardEntity> strategyAwardEntities=strategyRepository.getStrategyAwardEntityByStrategyIdAndAwardId(strategyId,entry.getValue());
            assembleStrategy(key,strategyAwardEntities);
        }
    }

    @Override
    public void assembleStrategy(String key, List<StrategyAwardEntity> strategyAwardEntities) {
        //获取最小中奖概率和中奖概率总和，用于构造抽奖map
        BigDecimal minRate = strategyAwardEntities.stream().map(StrategyAwardEntity::getAwardRate).min(BigDecimal::compareTo).get();
        BigDecimal totalRate=new BigDecimal(0);
        for (StrategyAwardEntity strategyAwardEntity : strategyAwardEntities) {
            totalRate=totalRate.add(strategyAwardEntity.getAwardRate());//BigDecimal进行计算，原始变量的值不会改变
        }
        BigDecimal totalNum = totalRate.divide(minRate,RoundingMode.HALF_UP);
        //构造抽奖map
        ArrayList<Integer> list=new ArrayList<>();
        for (StrategyAwardEntity strategyAwardEntity : strategyAwardEntities) {
            for(int i = 0; i<totalNum.multiply(strategyAwardEntity.getAwardRate()).setScale(0, RoundingMode.CEILING).intValue(); ++i) {
                list.add(strategyAwardEntity.getAwardId());
            }
        }
        Collections.shuffle(list);//进行洗牌，将相同的奖励洗牌到不同位置，增加随机性
        HashMap<Integer,Integer> map=new HashMap<>();
        for (int i = 0; i < list.size(); i++) {
            map.put(i,list.get(i));
        }
        //将抽奖map保存到缓存中
        strategyRepository.restoreLotteryMap(key,list.size(),map);
    }

    @Override
    public int lottery(Long strategyId) {
        return lottery(strategyId,"");
    }

    public int lottery(Long strategyId,String ruleWeightValue) {
        int range=strategyRepository.getLotteryRange(strategyId+(ruleWeightValue.isEmpty()?"":"_")+ruleWeightValue);
        HashMap<Integer,Integer> map=strategyRepository.getLotteryMap(strategyId+(ruleWeightValue.isEmpty()?"":"_")+ruleWeightValue);
        Integer awardId = map.get(new Random().nextInt(range));
        return awardId;
    }
}
